package com.captain.leetcode;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * @author captain
 * @Des 请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ，验证已经填入的数字是否有效即可。
 * <p>
 * 数字 1-9 在每一行只能出现一次。
 * 数字 1-9 在每一列只能出现一次。
 * 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。（请参考示例图）
 * 数独部分空格内已填入了数字，空白格用 '.' 表示。
 * <p>
 * 注意：
 * <p>
 * 一个有效的数独（部分已被填充）不一定是可解的。
 * 只需要根据以上规则，验证已经填入的数字是否有效即可。
 * @Date 2021/7/18 9:45
 */
public class 有效的数独36 {

    public static boolean isValidSudoku(char[][] board) {
        //暴力求解,依次判断三个条件是否成立
        //1.判断每一行
        for (int i = 0; i < 9; i++) {
            if (!isValidRows(board[i])) {
                return false;
            }
        }
        //2.检查每一列
        for (int i = 0; i < 9; i++) {
            if (!isValidCols(i, board)) {
                return false;
            }

        }
        //检查小的方格是否存在重复的
        //外循环定义行 i = 0  j = 0 , 3 , 9
        //3.判断每一个小格子
        for (int i = 0; i < 9; i += 3) {
            //内循环定义列数,一次三列
            for (int j = 0; j < 9; j += 3) {
                if (!isValidSmall(i, j, board)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * @param row   开始行数
     * @param col   开始列数
     * @param board 原二维数组
     */
    //检查小方格
    public static boolean isValidSmall(int row, int col, char[][] board) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                int rown = row + i;
                int coln = col + j;
                char c = board[rown][coln];
                if (c != '.') {
                    if (map.getOrDefault(c, 0) != 0) {
                        return false;
                    }
                    map.put(c, 1);
                }
            }
        }
        return true;
    }

    //检查每一列是否有重复元素
    private static Boolean isValidCols(int cole, char[][] board) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (char[] chars : board) {
            //每一列的数
            char c = chars[cole];
            if (c != '.') {
                if (map.getOrDefault(c, 0) != 0) {
                    return false;
                }
                map.put(c, 1);
            }
        }
        return true;
    }

    //检查每一行是否存在相同的
    private static Boolean isValidRows(char[] chars) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (char c : chars) {
            //存在值
            if (c != '.') {
                if (map.getOrDefault(c, 0) != 0) {
                    return false;
                }
                map.put(c, 1);
            }
        }
        return true;
    }


    public static void main(String[] args) {
        char[][] arr = new char[9][9];
        arr[0] = new char[]{'5', '3', '.', '.', '7', '.', '.', '.', '.'};
        arr[1] = new char[]{'6', '.', '.', '1', '9', '5', '.', '.', '.'};
        arr[2] = new char[]{'.', '9', '8', '.', '.', '.', '.', '6', '.'};
        arr[3] = new char[]{'8', '.', '.', '.', '6', '.', '.', '.', '3'};
        arr[4] = new char[]{'4', '.', '.', '8', '.', '3', '.', '.', '1'};
        arr[5] = new char[]{'7', '.', '.', '.', '2', '.', '.', '.', '6'};
        arr[6] = new char[]{'.', '6', '.', '.', '.', '.', '2', '8', '.'};
        arr[7] = new char[]{'.', '.', '.', '4', '1', '9', '.', '.', '5'};
        arr[8] = new char[]{'.', '.', '.', '.', '8', '.', '.', '7', '9'};
        //外循环控制行数
        for (int i = 0; i < 9; i += 3) {
            for (int j = 0; j < 9; j += 3) {
                //i 行数 j 列数
                listByCols(i, j, arr);
            }
        }
    }

    //0,0 0,1,0,2
    //0,0 1,0 2,0
    // 0,1 1,1 2,1
    // 0,3 1,3 2,3
    public static void listByCols(int row, int col, char[][] arr) {
        //谁在变 , 行在变, 列没有变
        //哪一列的多少行
        for (int i = 0; i < 3; i++) {
            //内循环 = 行数
            for (int j = 0; j < 3; j++) {
                int rown = row + i;
                int coln = col + j;
                char c = arr[rown][coln];
                if (c != '.') {
                    System.out.println(c);
                }
            }
        }
    }
}
